
#include "includes.h"
#include "structs.h"
#include "declares.h"
/* Author: cong
 * Date: Feb 15
 * File: client.c
 */  
/* the purpose of this file is to provide 
 * a class that reads vfile and efile and
 * produce an rfile that can be used as a
 * partition strategy
 */
/* here goes the definitions of vfile, efile and rfile
 * that is, the input of this module
 * suppose we have an undirected graph of vn vertices
 * and en edges.
 * 
 * vfile has vn lines with each line `vid a0 a1 ...'(no vsize && at least one a0)
 * efile has en lines with each line `src dst a0 a1 ...'(at least one a0)
 * rfile has vn lines with each line `vid fid'
 * 
 * note that the index of vertices starts from 1 (NOT 0)
 * the basic idea of this module is coding a series of
 * functions that converts from one representation to
 * another. Basically they are:
 * 
 * File: FILE *vfile, *efile, *rfile 
 * Vector: igraph_vector_ptr_t *edges, *vertices 
 * Igraph: igraph_t *igraph_graph
 * Adjlist: idx_t *metis_xadj, *metis_adjncy
 * 
 * for these functions:
 * 
 * precondition: the From params is garuanteed (inited, opened) by caller (but not necessarily 
 * correct in format, detecting errors is the responsibility of the functions)
 * 
 * postcondition: the correctness of To params is garuanteed by the functions 
 * if the From is correct then the To must be inited and correctly calculated
 */ 

/* Parse File vfile and store it in Vector vertices 
 * Input:
 * vfile: described as above
 * ncon: number of attributes attached to a single vertex
 * Ouput:
 * vn: pointer to number of vertices 
 * vertices: pointer to a  igraph_vector_ptr_t.
 * each entry points to a vertex_t structure
 * Time: O(vn)
 */


int vfile2vertices(FILE *vfile, int ncon, igraph_vector_ptr_t *vertices)
{
        int vn = 0;
        int vid, iattr;
        char *buffer = NULL; 
        ssize_t read;
        size_t len;
        struct vertex_t *pvertex;

        igraph_vector_ptr_init(vertices, 0);
        igraph_vector_ptr_set_item_destructor(vertices,free);
        while(-1 != (read = getline(&buffer, &len, vfile))) 
        {
                FILE *sstream = fmemopen(buffer, len, "r");
                if(1 != fscanf(sstream, "%d", &vid) ) {
                        continue;
                }
                vn++;
                pvertex = (struct vertex_t*) xmalloc(sizeof(struct vertex_t));
                pvertex->vid = vid-1;
                pvertex->attr = (int*) calloc(sizeof(int), ncon);
                pvertex->ncon = ncon;
                pvertex->vsize=0;
                pvertex->fids=xmalloc(sizeof(igraph_vector_int_t));
                igraph_vector_int_init(pvertex->fids,0);
                pvertex->locid=0;
                pvertex->fid=0;
                for(int i=0;i<ncon;++i) 
                {
                        fscanf(sstream, "%d", &iattr);
                        pvertex->attr[i] = iattr;
                }
                igraph_vector_ptr_push_back(vertices, pvertex);
                fclose(sstream);
        }
        free(buffer);
        igraph_vector_ptr_set_item_destructor(vertices, vertex_free);

        for(int i=0;i<vn;i++) {
                struct vertex_t *pv = VECTOR(*vertices)[i];
                /* print_vertex(stderr, pv); */
                printl_vertex(pv);
        }
        return vn;
}

/* for testing purpose wrapper */
int call_vfile2vertices(char *filename, int ncon, igraph_vector_ptr_t *vertices)
{
        zlog_category_t *mylog = zlog_get_category("mylog");
        FILE *vfile = fopen(filename, "r");
        if(!vfile) {
                zlog_error(mylog,  "vfile is null");
                exit(1);
        }
        if(!vertices) {
                zlog_error(mylog, "vertices is null");
                exit(1);
        }
        if( ncon < 1) {
                zlog_error(mylog, "ncon < 1");
                exit(1);
        }
        int vn = vfile2vertices(vfile, ncon , vertices);
        if (-1 == vn) {
                zlog_error(mylog, "vfile2vertices failed");
                exit(1);
        }

        zlog_info(mylog, "vfile2vertices succeeded , %d\n",vn);
        return vn;

}


/* Parse an efile and store these edges into edges
 * Input: efile: opened File described as above
 * Output: edges: Vector of edge_t
 * Time: O(en)
 */ 

int efile2edges(FILE *efile, igraph_vector_ptr_t *edges)
{
        int src, dst, attr;
        ssize_t read;
        size_t len;
        struct edge_t *pedge = NULL;
        int en=0;
        char *buffer = NULL;

        igraph_vector_ptr_init(edges, 0);
        igraph_vector_ptr_set_item_destructor(edges,free);
        while(-1 != (read = getline(&buffer, &len, efile))) 
        {
                if(3 != sscanf(buffer , "%d%d%d", &src, &dst, &attr)) 
                        continue;
                pedge = (struct edge_t*) xmalloc(sizeof(struct edge_t));
                pedge->src = src -1 ;
                pedge->dst = dst -1 ;
                pedge->attr = attr;
                assert(en >= 0);
                pedge->eid = en;
                en ++;
                igraph_vector_ptr_push_back(edges, pedge);
        }
        free(buffer);
        for(int i=0;i<en;i++) {
                struct edge_t *pedge = igraph_vector_ptr_e(edges,i);
                printl_edge(pedge);
                /* print_edge(stderr, pedge); */
        }
        return en;
}

int call_efile2edges(const char *filename, igraph_vector_ptr_t *edges)
{
        int en;
        FILE *efile;
        zlog_category_t *mylog = zlog_get_category("mylog");
        efile = fopen(filename, "r");

        if( NULL == efile ) { 
                zlog_error(mylog, "failed to open efile");
                exit(1);
        } 
        en = efile2edges(efile, edges);
        if(en == -1){
                zlog_error(mylog, "efile2edges failed");
                exit(1);
        }
        zlog_info(mylog, "efile2edges succeeded, en=%d", en);
        return en;
}

/* Convert Vectors of edges and vertices to
 * igraph_adjlist_t(an array of adjlists)
 * note that the adjlist of each vertex is 
 * in fact of igraph_vector_int_t so only 
 * vertex id is retained in this structure
 * 
 * Input: as described in vector2adjlist
 * Ouput: iadjlist 
 * Time: O(en + vn)
 */ 


int vector2igraph_adjlist(int vn, int en, 
                igraph_vector_ptr_t *vertices,
                igraph_vector_ptr_t *edges,
                igraph_adjlist_t *iadjlist)


{
        igraph_adjlist_init_empty(iadjlist, vn);
        struct edge_t *pedge;
        int dst, src ;
        igraph_vector_int_t *adjlist;

        for(int i=0;i<en;++i) { 
                /* pedge = VECTOR(*edges)[i]; */
                pedge=igraph_vector_ptr_e(edges,i);
                src = pedge->src;
                dst= pedge->dst;
                adjlist = igraph_adjlist_get(iadjlist, src);
                igraph_vector_int_push_back(adjlist, dst);
                adjlist = igraph_adjlist_get(iadjlist, dst );
                igraph_vector_int_push_back(adjlist, src);

        }
#ifndef NDEBUG
        igraph_adjlist_fprint(iadjlist,stderr);
#endif
        return 0;
}


/* the same function that converts Vectors to 
 * Adjlist, but using the my_adjlist_t where
 * each element of an adjlist points to a
 * edge_t structure 
 */

struct edge_t *swap_and_store(struct edge_t *e)
{
        struct edge_t *pedge = xmalloc(sizeof(struct edge_t));
        memcpy(pedge, e, sizeof(struct edge_t));
        pedge->dst = e->src;
        pedge->src = e->dst;
        return pedge;
}

int vector2my_adjlist(
                igraph_vector_ptr_t *vertices,
                igraph_vector_ptr_t *edges,
                my_adjlist_t *iadjlist)


{
        int vn = igraph_vector_ptr_size(vertices);
        int en = igraph_vector_ptr_size(edges);

        int err = my_adjlist_init_empty(iadjlist, vn);
        if(err)
                return -1;
        struct edge_t *pedge;
        int dst, src ;
        igraph_vector_ptr_t *adjlist;

        for(int i=0;i<en;++i) { 
                pedge=igraph_vector_ptr_e(edges,i);
                src = pedge->src;
                dst= pedge->dst;
                adjlist = my_adjlist_get(iadjlist, src);
                igraph_vector_ptr_push_back(adjlist, pedge);
        }
        printl_my_adjlist(iadjlist);
        /* my_adjlist_print(stderr,iadjlist); */
        return 0;
}

/* Convert my_adjlist_t to adjlist in METIS format 
 * Input: al: undirected adjlist whose element is struct edge_t
 * Ouput: xadj, adjncy, vwgt, adjwgt: 
 *      igraph_vector_int_t 
 */

int my_adjlist2adjlist(
                igraph_vector_ptr_t *vertices,
                my_adjlist_t *al,
                igraph_vector_int_t *xadj,
                igraph_vector_int_t *adjncy,
                igraph_vector_int_t *vwgt,
                igraph_vector_int_t *adjwgt)
{
        int vn = al->vn;                
        igraph_vector_int_init(xadj, 0);
        igraph_vector_int_init(adjncy, 0);
        igraph_vector_int_init(vwgt, 0);
        igraph_vector_int_init(adjwgt, 0);
        int index=0;
        int ncon=((struct vertex_t*) VECTOR(*vertices)[0]) ->ncon;

        for(int i=0;i<vn;++i) {
                for(int j=0;j<ncon;++j) {
                        struct vertex_t *pattr = igraph_vector_ptr_e(vertices,i);
                        /* struct vertex_t *pattr = VECTOR(*vertices)[i]; */
                        igraph_vector_int_push_back(vwgt, pattr->attr[j]);
                }
        }

        for(int i=0;i<vn;++i) {
                igraph_vector_int_push_back(xadj, index);
                igraph_vector_ptr_t *pa = &(al->al[i]);
                int size = igraph_vector_ptr_size(pa);
                for(int j=0;j<size;++j) {
                        struct edge_t *pe = igraph_vector_ptr_e(pa,j);
                        /* struct edge_t *pe = VECTOR(*pa)[j]; */
                        igraph_vector_int_push_back(adjncy, pe->dst);
                        igraph_vector_int_push_back(adjwgt, pe->attr);
                        index++;
                }
        }
        igraph_vector_int_push_back(xadj, index);
#ifndef NDEBUG
        igraph_vector_int_fprint(xadj, stderr);
        igraph_vector_int_fprint(adjncy, stderr);
        igraph_vector_int_fprint(vwgt, stderr);
        igraph_vector_int_fprint(adjwgt, stderr);
#endif 
        return 0;
}

/* Convert from vertices and edges to metis_adjlist
 * Input: vn: number of vertices
 *        en: number of edges
 *      ncon: number of attrs of a single vertex 
 * Ouput: xadj: vertex vid 's adjlist is stored in range 
 *              [xadj[vid], xadj[vid+1]]
 *              len -> vn+1
 *      adjncy: stores adjlists for all vertices continuously
 *      vwgt:   vertex vid 's weight(s) is stored within
 *              [vid * ncon, (vid+1) * ncon]
 *      adjwgt: the edge eid is stored at adjncy[eid]
 *              whose weight is stored at adjwgt[eid]
 * Time: O(vn * en)
 */

int vector2adjlist(int vn, int en, int ncon,
                igraph_vector_ptr_t *vertices,
                igraph_vector_ptr_t *edges,
                idx_t **xadj,
                idx_t **adjncy,
                idx_t **vwgt,
                idx_t **adjwgt)
{
        struct edge_t *pedge;
        int *pattr, dst, src, attr;
        int index=0, subsrp=0;

        *xadj = xmalloc(sizeof(idx_t)*(vn+1));
        *adjncy = xmalloc(sizeof(idx_t)*2*en);
        *vwgt = xmalloc(sizeof(idx_t)*ncon *vn);
        *adjwgt = xmalloc(sizeof(idx_t)*en*2);

        for(int i=0;i<vn;++i) {
                for(int j=0;j<ncon;++j) {
                        int pos = i * ncon  + j ;
                        /* struct vertex_t *pattr = VECTOR(*vertices)[i]; */
                        struct vertex_t *pattr = igraph_vector_ptr_e(vertices,i);
                        (*vwgt)[pos] = pattr->attr[j];
                }
        }
        for(int i=0;i<vn;i++) {
                (*xadj)[subsrp++] = index;
                for(int j=0;j<en;++j) {
                        pedge = VECTOR(*edges)[j];
                        src = pedge->src;
                        dst= pedge->dst;
                        attr = pedge->attr;
                        if(src != i && dst != i) 
                                continue;
                        int vv = src == i ? dst : src;
                        (*adjncy)[index] = vv;
                        (*adjwgt)[index] = attr;
                        ++index;
                        /* printf("%d ", vv); */
                }
                /* puts("\n"); */
        }
        (*xadj)[subsrp] = index;

        return 0;
}

int vector2adjlistEX(igraph_vector_ptr_t *vertices,
                igraph_vector_ptr_t *edges,
                igraph_vector_int_t *xadj,
                igraph_vector_int_t *adjncy,
                igraph_vector_int_t *vwgt,
                igraph_vector_int_t *adjwgt,
                int ncon)
{

        struct edge_t *pedge;
        int *pattr, dst, src, attr;
        int index=0, subsrp=0;
        int vn, en;

        vn =  igraph_vector_ptr_size(vertices);
        en = igraph_vector_ptr_size(edges) ;
        igraph_vector_int_init(xadj, 0);
        igraph_vector_int_init(adjncy, 0);
        igraph_vector_int_init(vwgt, 0);
        igraph_vector_int_init(adjwgt, 0);

        for(int i=0;i<vn;++i) {
                for(int j=0;j<ncon;++j) {
                        int pos = i * ncon  + j ;
                        /* pattr = VECTOR(*vertices)[i]; */
                        struct vertex_t *pattr = igraph_vector_ptr_e(vertices,i);
                        igraph_vector_int_push_back(vwgt, pattr->attr[j]);
                        /* (*vwgt)[pos] = pattr[j]; */
                }
        }

        for(int i=0;i<vn;i++) {
                igraph_vector_int_push_back(xadj, index);
                for(int j=0;j<en;++j) {
                        /* pedge = VECTOR(*edges)[j]; */
                        pedge=igraph_vector_ptr_e(edges,i);
                        src = pedge->src;
                        dst= pedge->dst;
                        attr = pedge->attr;
                        if(src != i && dst != i) 
                                continue;
                        int vv = src == i ? dst : src;
                        igraph_vector_int_push_back(adjncy, vv);
                        igraph_vector_int_push_back(adjwgt, attr);
                        /* VECTOR(*adjncy)[index] = vv; */
                        ++index;
                }
        }
        igraph_vector_int_push_back(xadj, index);

#ifndef NDEBUG
        igraph_vector_int_fprint(xadj, stderr);
        igraph_vector_int_fprint(adjncy, stderr);
        igraph_vector_int_fprint(vwgt, stderr);
        igraph_vector_int_fprint(adjwgt, stderr);

#endif
        return 0;
}

int call_vector2adjlist(
                int ncon,
                igraph_vector_ptr_t *vertices,
                igraph_vector_ptr_t *edges
                )
{
        int vn =  igraph_vector_ptr_size(vertices);
        int en = igraph_vector_ptr_size(edges) ;

        idx_t *xadj, *adjncy, *vwgt, *adjwgt;
        int result;
        result = vector2adjlist(vn, en ,
                        ncon,
                        vertices, 
                        edges,
                        &( xadj ),
                        &( adjncy ),
                        &( vwgt ),
                        &( adjwgt )
                        );
        adjlist_printf(vn,en,ncon, xadj, adjncy, vwgt, adjwgt);
        return 0;
}

int dimacs2files(FILE *dimacs, int npart,FILE *vfile, FILE *efile, FILE *rfile)
{
        igraph_t undirected_graph;
        igraph_adjlist_t iadjlist;
        zlog_category_t *mylog = zlog_get_category("mylog");
        
        zlog_info(mylog,"igraph_read_graph_dimacs begin");
        int rs = igraph_read_graph_dimacs(&undirected_graph, dimacs, 0,0,0,0,0,0);
        if(rs != IGRAPH_SUCCESS) {
                zlog_error(mylog, "igraph_read_graph_dimacs failed");
                return -1;
        }
        zlog_info(mylog,"igraph_read_graph_dimacs finish");

        igraph_vector_int_t xadj;
        igraph_vector_int_t adjncy;
        int vn = igraph_vcount(&undirected_graph);
        int en = igraph_ecount(&undirected_graph);
        
        zlog_info(mylog, "Graph to Adjlist begin"); 
        rs = igraph_adjlist_init(&undirected_graph,&iadjlist,IGRAPH_ALL);
        if(rs != IGRAPH_SUCCESS) {
                zlog_error(mylog, "igraph_adjlist_init failed");
                return -1;
        }
        zlog_info(mylog, "Graph to Adjlist finish, vn=%d, en=%d",vn,en);

        zlog_info(mylog, "Preparation for partitioning begin");
        igraph_vector_int_init(&xadj, 0);
        igraph_vector_int_init(&adjncy, 0);
        idx_t *part = calloc(sizeof(idx_t), vn);
        idx_t edgecut;
        int index=0; 
        int ncon=1;
        for(int i=0;i<vn;++i) {
                igraph_vector_int_push_back(&xadj, index);
                igraph_vector_int_t *pa = igraph_adjlist_get(&iadjlist,i);
                int size = igraph_vector_int_size(pa);
                for(int j=0;j<size;++j) {
                        int pe = VECTOR(*pa)[j];
                        igraph_vector_int_push_back(&adjncy, pe);
                        index++;
                }
        }
        igraph_vector_int_push_back(&xadj, index);
        zlog_info(mylog, "Preparation for partitioning finish");

        zlog_info(mylog, "METIS_PartGraphKway begin");
        rs = METIS_PartGraphKway(&vn,&ncon,xadj.stor_begin,adjncy.stor_begin,0,0,0,&npart,0,0,0,&edgecut,part);
        if(rs != METIS_OK) {
                zlog_error(mylog, "METIS_PartGraphKway failed");
                return -1;
        }
        zlog_info(mylog, "METIS_PartGraphKway finish");

        zlog_info(mylog, "Generating rfile...");
        print_partition(rfile, part, vn);
        zlog_info(mylog, "Generatiion done, edgecut is %d", edgecut);

        zlog_info(mylog, "Generating vfile...");

        for(int i=0;i<vn;++i) {
                fprintf(vfile, "%d 0\n", i+1);
        }
        zlog_info(mylog,"Generatiion done, use the vfile with ncon=1, vwgt=NULL, vsize=NULL");

        zlog_info(mylog, "Generating efile...");
        igraph_es_t alles;
        igraph_es_all(&alles, IGRAPH_EDGEORDER_ID);
        igraph_eit_t alleit;
        igraph_eit_create(&undirected_graph,alles,&alleit);
        while(!IGRAPH_EIT_END(alleit))
        {
                int eid = IGRAPH_EIT_GET(alleit);
                int from, to;
                igraph_edge(&undirected_graph,eid,&from,&to);
                fprintf(efile,"%d %d 1\n",from+1,to+1);
                IGRAPH_EIT_NEXT(alleit);
        }
        zlog_info(mylog, "Generatiion done, use the efile with adjwgt=NULL");
/* #ifndef NDEBUG */
/*         zlog_info (mylog, "Showing intermedia result.."); */
/*         igraph_adjlist_fprint(&iadjlist,stderr); */
/*         igraph_vector_int_fprint(&xadj,stderr); */
/*         igraph_vector_int_fprint(&adjncy,stderr); */
/*         print_partition(stderr, part, vn); */
/* #endif */
        igraph_eit_destroy(&alleit);
        free(part);
        igraph_vector_int_destroy(&xadj);
        igraph_vector_int_destroy(&adjncy);
        igraph_destroy(&undirected_graph);
        fclose(dimacs);
        fclose(rfile);
        fclose(vfile);
        fclose(efile);
        return 0;
}

/* let clearify the stuffs about metis's input format:
 * line 1 will be header line i.e.
 * (n m [fmt] [ncon])
 * remaining lines describe info about a single vertex 
 * per line in a adjlist favour.
 * 
 * line i: s w1 w2 ... w[ncon] v1 e1 v2 e2 ...
 * 
 * show more details:
 * i: implicit vertex i described about in this line 
 * s: vsize
 * w[i]: vwgt
 * v[i]: vertex adj to i
 * e[i]: adjwgt[i] i.e. weight of edge {i, v[i]}
 * ncon: number of constrains on vertex i
 * about fmt:
 * 001: has adjwgt  (or NULL)
 * 010: has vwgt (or NULL)
 * 100: has vsize (or NULL)
 * if no fmt feild is provided, adjwgt , vwgt and vsize 
 * are assume to be all 1
 * note that comment starts from `%'
 */

/* this function requires fmt string from caller and check
 * against the actual content of struct edge_t and vertex_t
 * to see if fmt is correct.
 * i.e.
 * pv->vsize == 0 -> no vsize
 * pv->ncon == 0 -> no vwgt
 * pe->attr == -1 -> no adjwgt(negative weight is currently not
 * supported)
 * 
 * normally for graph generated from vfile and efile format,
 * fmt will be 011 (with vwgt and adjwgt, without vsize)
 */

int my_adjlist2gpmetis(my_adjlist_t *al, int en,
               igraph_vector_ptr_t *vertices, char *fmt,
              FILE *gpmetis)
{
        struct vertex_t *pv = VECTOR(*vertices)[0];
        struct edge_t *pe = VECTOR(*my_adjlist_get(al,0))[0];
        int ncon = pv->ncon;
        int vn = al->vn;
        int hvsize = pv->vsize != 0;
        int hvwgt = pv->ncon != 0;
        int hadjwgt = pe->attr != -1;

        zlog_category_t *mylog = zlog_get_category("mylog");
        if(fmt[2]=='1' && !hadjwgt) {
                zlog_error(mylog, "adjwgt not found");
                return -1;
        }
        if(fmt[1]=='1' && !hvwgt) {
                zlog_error(mylog, "vwgt not found");
                return -1;
        }
        if(fmt[0]=='1' &&!hvsize) {
                zlog_error(mylog, "vsize not found");
                return -1;
        }

        fprintf(gpmetis, "%d %d %s", vn, en, fmt);
        if(hvwgt)
                fprintf(gpmetis, " %d\n", ncon); // ncon will be 1
        else
                fputs("\n", gpmetis);

        for(int i=0;i<vn;++i) {
                pv = VECTOR(*vertices)[i];
                if(hvsize)
                        fprintf(gpmetis,"%d ", pv->vsize);
                for(int j=0;j<ncon;++j) {
                        fprintf(gpmetis, "%d ", pv->attr[j]);
                }

                igraph_vector_ptr_t *pa = my_adjlist_get(al,i);
                int size = igraph_vector_ptr_size(pa);
                for(int k=0;k<size;++k) {
                        pe = VECTOR(*pa)[k];
                        fprintf(gpmetis,"%d ", pe->dst+1);
                        if(hadjwgt)
                                fprintf(gpmetis, "%d ", pe->attr);
                }
                fputs("\n", gpmetis);
        }

        // check with graphchk in the caller 
        return 0;
}

/* print textual info for an adjlist in METIS format */      
void adjlist_printf(int vn, int en, int ncon,
                idx_t *xadj, idx_t *adjncy,
                idx_t *vwgt, idx_t *adjwgt)
{
        printf("xadj:\n");
        for(int i=0;i<vn+1;++i) {
                printf("%d ", xadj[i]);
        }
        puts("\n");
        printf("adjncy:\n");
        for(int i=0;i<2*en;++i) {
                printf("%d ", adjncy[i]);
        }

        puts("\n");


        printf("vwgt:\n");
        for(int i=0;i<vn;++i) {
                printf("%d: ", i);
                for(int j=0;j<ncon;++j) {
                        printf("%d ", vwgt[j]);
                }
                puts("\n");
        }

        puts("\n");

        printf("adjwgt:\n");
        for(int i=0;i<2*en ;++i) {
                printf("%d ", adjwgt[i]);
        }

        puts("\n");
}


void print_partition(FILE *stream, idx_t *part, idx_t nvtxs)
{
        for(int i=0;i<nvtxs;i++) {
                fprintf(stream, "%d %d\n",i+1,  part[i]);
        }
}

int rfile2fragtable(FILE *rfile, int vn, igraph_vector_int_t *fragtable)
{
        int fid,vid;
        igraph_vector_int_init(fragtable,vn);
        // fix the while(feof(... bug
        while(2 ==fscanf(rfile, "%d %d", &vid, &fid))
        {
                VECTOR(*fragtable)[vid-1]=fid;
        }
        return vn;
}

int verfile2gpmetis(char*vfilename , char*efilename, int ncon, char *graphfile) 
{
        igraph_vector_ptr_t vertices, edges;
        my_adjlist_t adjlist;
        FILE *gpmetis = fopen(graphfile, "w");
        FILE *vfile=fopen(vfilename,"r");
        FILE *efile=fopen(efilename,"r");

        int vn = vfile2vertices(vfile, ncon, &vertices);
        int en = efile2edges(efile, &edges);
        
        fprintf(gpmetis,"%% this file is generated by GRAPE from vfile %s, efile %s\n",
                        vfilename, efilename);

        int rs = vector2my_adjlist(&vertices,&edges, &adjlist);
        rs = my_adjlist2gpmetis(&adjlist,en,&vertices,"011",
                        gpmetis);

        fclose(vfile);
        fclose(efile);
        fclose(gpmetis);
        return rs;
}

int dimacs2gpmetis(char *dimacsfile, char *graphfile)
{
        igraph_t graph;
        igraph_adjlist_t adjlist;
        int rs=0;
        zlog_category_t *mylog = zlog_get_category("mylog");
        
        FILE *dimacs=fopen(dimacsfile,"r"); 
        if(!dimacs) {
                zlog_error(mylog,"cannot open %s for reading",dimacsfile);
                return -1;
        }
        igraph_read_graph_dimacs(&graph,dimacs,0,0,0,0,0,0);
        igraph_adjlist_init(&graph,&adjlist,IGRAPH_ALL);

        int vn=igraph_vcount(&graph);
        int en=igraph_ecount(&graph);
        FILE *gpmetis=fopen(graphfile,"w");

        fprintf(gpmetis,"%% this file is generated by dimacs2gpmetis from %s\n",dimacsfile);
        fprintf(gpmetis,"%d %d\n", vn,en);
        
        for(int i=0;i<vn;++i) {
                igraph_vector_int_t *pi=igraph_adjlist_get(&adjlist,i);
                int size=igraph_vector_int_size(pi);
                for(int j=0;j<size;++j) {
                        int vid=VECTOR(*pi)[j];
                        fprintf(gpmetis,"%d ", vid+1);
                }
                fputs("\n", gpmetis);
        }

        return rs;



}

